package connectors;

import java.io.File;
import java.util.ArrayList;

import javax.jws.WebParam.Mode;
import javax.print.attribute.standard.MediaSize.Other;
import javax.swing.JOptionPane;

import model.DocumentEA;
import model.EAItem;
import model.MainModel;

import org.sparx.App;
import org.sparx.Collection;
import org.sparx.Diagram;
import org.sparx.DiagramLink;
import org.sparx.DiagramObject;
import org.sparx.Element;
import org.sparx.Project;
import org.sparx.Repository;
import org.sparx.TaggedValue;

import utils.ControllerUtils;
import utils.MessageHandler;
import utils.ObjectUtils;
import utils.StringUtils;

import com.sun.xml.internal.ws.api.message.Message;

import Logger.MainLogger;

public class EAConnector {
	public static String modelPath = "";
	private Repository repository;
	private static MainLogger LOGGER;
	private static String SEP = File.separator;

	public EAConnector(String modelPath) {

		LOGGER = new MainLogger("resources/log.log");
		this.modelPath = modelPath;
		this.repository = new Repository();
		if (!this.modelPath.equals("")) {
			repository.OpenFile(this.modelPath);
			LOGGER.log("File has been sucessfully opened");
		} else {
			JOptionPane.showMessageDialog(null, "File path is empty");
			return;
		}
	}

	public Repository getRepository() {

		return this.repository;
	}

	// create sample stereotypes test serviceDATA/PSLIntMaster.eap
	public void createSampleStructure() {
		LOGGER.log("started creating a sample structure");
		Project projectInterface = repository.GetProjectInterface();
		App rep = repository.GetApp();
		// get all models properties where main packages are situated
		org.sparx.Package Model = repository.GetModels().GetAt((short) 0);
		org.sparx.Package classpak = Model.GetPackages().AddNew(
				"Business object Model (BOM)", "Class");
		Model.GetPackages().Refresh();
		classpak.Update();

		classpak.GetDiagrams()
				.AddNew("Business object Model (BOM)", "Component").Update();

		classpak.GetDiagrams().Refresh();
		classpak.Update();

		Element el1 = classpak.GetElements().AddNew("Class1", "Class");
		el1.GetAttributes().AddNew("attribute1", "int").Update();
		el1.GetAttributes().Refresh();
		el1.GetAttributes().AddNew("attribute2", "string").Update();
		el1.GetAttributes().Refresh();
		el1.GetMethods().AddNew("method1", "Method").Update();
		el1.GetMethods().Refresh();
		el1.GetMethods().AddNew("method2", "Method").Update();
		el1.GetMethods().Refresh();
		el1.GetTaggedValues().AddNew("tagged1", "value1").Update();
		el1.GetTaggedValues().AddNew("tagged2", "value2").Update();
		el1.GetTaggedValues().Refresh();
		classpak.Update();

		Element el2 = classpak.GetElements().AddNew("Class2", "Class");
		el2.GetAttributes().AddNew("attribute1", "int").Update();
		el2.GetAttributes().Refresh();
		el2.GetAttributes().AddNew("attribute2", "string").Update();
		el2.GetAttributes().Refresh();
		el2.GetMethods().AddNew("method1", "Method").Update();
		el2.GetMethods().Refresh();
		el2.GetMethods().AddNew("method2", "Method").Update();
		el2.GetMethods().Refresh();
		el2.GetTaggedValues().AddNew("tagged1", "value1").Update();
		el2.GetTaggedValues().AddNew("tagged2", "value2").Update();
		el2.GetTaggedValues().Refresh();
		classpak.Update();

		Element el3 = classpak.GetElements().AddNew("Class3", "Class");
		el3.GetAttributes().AddNew("attribute1", "int").Update();
		el3.GetAttributes().Refresh();
		el3.GetAttributes().AddNew("attribute2", "string").Update();
		el3.GetAttributes().Refresh();
		el3.GetMethods().AddNew("method1", "Method").Update();
		el3.GetMethods().Refresh();
		el3.GetMethods().AddNew("method2", "Method").Update();
		el3.GetMethods().Refresh();
		el3.GetTaggedValues().AddNew("tagged1", "value1").Update();
		el3.GetTaggedValues().AddNew("tagged2", "value2").Update();
		classpak.Update();

		Model.GetElements().Refresh();
		Model.GetDiagrams().Refresh();
		Model.Update();
		repository.CloseFile();
		LOGGER.log("Sample model has been sucessfully created");

	}

	public void importDocumentStructure(ArrayList<DocumentEA> DocEA) {
		Project projectInterface = repository.GetProjectInterface();
		App rep = repository.GetApp();
		LOGGER.log("File has been sucessfully opened");
		System.out.println("Models quantity "
				+ repository.GetModels().GetCount());

		ArrayList<org.sparx.Element> correls = new ArrayList<org.sparx.Element>();

		org.sparx.Package Model = repository.GetModels().GetAt((short) 0);
		org.sparx.Package v13B = Model.GetPackages().GetByName("Release 13B");
		org.sparx.Package PSLDE = Model.GetPackages().GetByName(
				"PSL Deutschland");
		org.sparx.Package PSLDE_BPM = PSLDE.GetPackages().GetByName(
				"Business Process Model");

		for (org.sparx.Element elts : PSLDE_BPM.GetElements()) {
			System.out.println(elts.GetName());
			System.out.println(elts.GetType());
			for (DocumentEA doea : DocEA) {
				for (String cols : doea.getMappingObjectNames()) {
					if (elts.GetName().equals(cols)
							&& elts.GetType().equals("Activity")) {
						if (!correls.contains(elts)) {
							correls.add(elts);
						}

					}
				}
			}

		}

		org.sparx.Package DM = v13B.GetPackages().GetByName("Document Model");
		org.sparx.Package TDs = DM.GetPackages().GetByName("TDs");
		org.sparx.Diagram dia = TDs.GetDiagrams().GetByName("TDs");
		Collection<org.sparx.DiagramObject> DOS = dia.GetDiagramObjects();

		for (DocumentEA dea : DocEA) {
			System.out.println("***********Schreiben Element********");
			System.out.println(dea.getName());
			Element elt = TDs.GetElements().AddNew(dea.getName(), "Artifact");
			elt.SetStereotype("document");
			elt.Update();
			elt.Refresh();
			elt.SetStereotypeEx("document");
			elt.Update();
			elt.Refresh();
			elt.SetVersion("1.0");
			elt.Update();
			elt.Refresh();
			elt.SetPhase("1.0");
			elt.Update();
			elt.Refresh();
			TaggedValue tv1 = elt.GetTaggedValues().AddNew(
					"PSL_INT_TD_NewOrChange", dea.getNewOrChange());
			tv1.Update();
			elt.GetTaggedValues().Refresh();
			TaggedValue tv2 = elt.GetTaggedValues().AddNew("PSL_INT_TD_Type",
					dea.getType());
			// Add the element to the diagram

			String styleString = "l=700;r=1000;t="
					+ String.valueOf(DocEA.indexOf(dea) * 100 + 50) + ";b="
					+ String.valueOf(DocEA.indexOf(dea) * 100 + 100) + ";";

			DiagramObject testDO = DOS.AddNew(styleString, "");
			testDO.SetElementID(elt.GetElementID());
			testDO.Update();

			// add link to processes

			for (org.sparx.Element el : correls) {
				//FIXME: Too slow exist in collection method
				if (existInCollection(dia.GetDiagramObjects(), el)) {
					String stylemappedObj = "l=100;r=250;t="
							+ String.valueOf(DocEA.indexOf(dea) * 50 + 25)
							+ ";b="
							+ String.valueOf(DocEA.indexOf(dea) * 50 + 50)
							+ ";";
					DiagramObject mappedObj = DOS.AddNew(stylemappedObj, "");
					mappedObj.SetElementID(el.GetElementID());
					mappedObj.Update();
					DOS.Refresh();
				}

				org.sparx.Connector connector = TDs.GetConnectors().AddNew(
						"Trace", "Association");
				connector.SetClientID(el.GetElementID());
				connector.SetSupplierID(elt.GetElementID());
				connector.Update();
				TDs.GetConnectors().Refresh();
				DiagramObject conn = DOS.AddNew("", "");
				conn.SetElementID(connector.GetConnectorID());
				conn.Update();
				DOS.Refresh();

			}

			tv2.Update();
			elt.GetTaggedValues().Refresh();
			elt.Refresh();
			TDs.GetElements().Refresh();
		}
		DOS.Refresh();
		DM.GetPackages().Refresh();
		v13B.GetPackages().Refresh();
		Model.Update();
		repository.CloseFile();
		System.out.println("Model is written");
	}

	public void readStructure() {
		LOGGER.log("Starting printing out XML structure");
		org.sparx.Package Model = repository.GetModels().GetAt((short) 0);
		for (org.sparx.Package pakk : Model.GetPackages()) {
			System.out.println("Pakage name: " + pakk.GetName());
			System.out.println("Pakage type: " + pakk.GetStereotypeEx());
			for (Diagram diag : pakk.GetDiagrams()) {
				System.out.println("	Diagram name: " + diag.GetName());
				System.out.println("	Diagram type: " + diag.GetType());
			}
			for (Element elt : pakk.GetElements()) {
				System.out.println("		element name: " + elt.GetName());
				System.out.println("		element type: " + elt.GetType());
			}

		}
		LOGGER.log("End printing out XML structure");

	}

	/**
	 * <a> this method returns an elemnt with a package type
	 * 
	 * @param Xpath
	 * @param pak
	 * @return current package
	 */
	public org.sparx.Package getPackageByXPath(String Xpath,
			org.sparx.Package pak) {
		if (Xpath.indexOf("[") != -1 || Xpath.indexOf("]") != -1) {
			MessageHandler.showSingleError("Only Directpath is supported");
			return null;
		}

		if (Xpath.startsWith("/")) {
			Xpath = Xpath.substring(1);
		}
		if (Xpath.startsWith("/")) {
			Xpath = Xpath.substring(1);
		}
		String currPakName = Xpath.substring(0, Xpath.indexOf("/"));
		String remainString = Xpath.substring(Xpath.indexOf("/"),
				Xpath.length());
		EAItem item = new EAItem();
		boolean found = false;
		// FIXME:RESOLVE THESE QUESTIONS
		for (org.sparx.Diagram dia : pak.GetDiagrams()) {

			if (dia.GetName().equals(currPakName) && !found) {
				ObjectUtils.setField(item, "diagram", dia);
				found = true;
			}
		}
		for (org.sparx.Element elem : pak.GetElements()) {

			if (elem.GetName().equals(currPakName) && !found) {
				ObjectUtils.setField(item, "element", elem);
				found = true;
			}
		}
		for (org.sparx.Package pakagea : pak.GetPackages()) {

			if (pakagea.GetName().equals(currPakName) && !found) {
				ObjectUtils.setField(item, "pakage", pakagea);
				found = true;
			}
		}
		// FIXME:END
		System.out.println(currPakName);
		System.out.println(remainString);
		org.sparx.Package currPak = null;
		if (StringUtils.isNotNullAndEmpty(currPakName)) {
			currPak = pak.GetPackages().GetByName(currPakName);
			if (!((Xpath.indexOf("/") == 0) || (Xpath.indexOf("/") == 1))) {
				getPackageByXPath(remainString, currPak);
			}
		}
		return currPak;
	}

	public boolean existInCollection(Collection<DiagramObject> collect,
			Object obj) {
		boolean exist = false;
		for (Object compObject : collect) {
			if (compObject.equals(obj)) {
				exist = true;
				break;
			}
		}
		return exist;
	}

	public static void main(String[] args) {
		final String sep = File.separator;

		String importFilePath = "DATA" + sep + "TD_PSL_INT_TD_InventoryCSV.csv";

		String outputFilePath = "DATA" + sep + "output.xls";

		String modelFilePath = System.getProperty("user.dir") + sep + "DATA"
				+ sep + "PSLIntAAS.eap";
		EAConnector eacon = new EAConnector(modelFilePath);
		org.sparx.Package pak = eacon
				.getPackageByXPath(
						"/Release 13B/Customization Model/Customizations PSL Int - not responsible",
						eacon.getRepository().GetModels().GetAt((short) 0));
		System.out.println("Pak " + pak.GetName());
	}
}
